<!-- 标签输入框组件 license by http://eleadmin.com -->
<template>
  <div class="ele-tags-input">
    <el-tag
      v-for="(item, index) in data"
      :key="index"
      :size="size"
      :type="type"
      :effect="effect"
      :closable="true"
      :disable-transitions="true"
      @close="onClose(index)"
    >
      {{ item }}
    </el-tag>
    <el-tooltip
      :value="edit && !!message"
      :content="message"
      placement="top"
      :manual="true"
      :transition="transition"
    >
      <el-input
        ref="input"
        :size="size"
        v-show="edit"
        v-model="text"
        :disabled="loading"
        :suffix-icon="loading ? 'el-icon-loading' : ''"
        :style="{ width: width }"
        @keyup.enter.native="onEdit"
        @blur="onEdit"
      />
    </el-tooltip>
    <el-button
      v-show="!edit"
      :size="size"
      :style="{ width: width }"
      @click="showEdit"
    >
      {{ placeholder }}
    </el-button>
  </div>
</template>

<script>
  export default {
    name: 'EleTagsInput',
    model: {
      prop: 'data',
      event: 'change'
    },
    props: {
      // 标签数据, v-model绑定
      data: Array,
      // 标签类型
      type: String,
      // 标签尺寸
      size: String,
      // 标签主题
      effect: String,
      // 输入框提示文字
      placeholder: {
        type: String,
        default: '+ New Tag'
      },
      // 输入框宽度
      width: {
        type: String,
        default: '90px'
      },
      // 是否唯一
      unique: {
        type: Boolean,
        default: true
      },
      // 唯一校验提示信息
      uniqueMessage: {
        type: String,
        default: '${value}已经存在'
      },
      // 自定义验证
      validator: [Function, Array],
      // 删除前回调
      beforeRemove: Function,
      // tooltip渐变动画
      transition: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        // 是否编辑状态
        edit: false,
        // 输入框值
        text: '',
        // 提示信息
        message: '',
        // 保存loading
        loading: false
      };
    },
    methods: {
      /* 显示编辑框 */
      showEdit() {
        this.edit = true;
        this.message = '';
        this.$nextTick(() => {
          this.$refs.input.$refs.input.focus();
        });
      },
      /* 添加tag */
      addTag(value) {
        this.edit = false;
        this.text = '';
        this.message = '';
        this.loading = false;
        this.$emit('change', this.data.concat([value]));
      },
      /* 保存编辑 */
      onEdit() {
        if (!this.text) {
          this.edit = false;
          this.message = '';
          return;
        }
        // 唯一验证
        if (this.unique && this.data.includes(this.text)) {
          this.message = this.uniqueMessage.replace('${value}', this.text);
          return;
        }
        // 自定义验证
        this.loading = true;
        if (typeof this.validator === 'function') {
          Promise.resolve(this.validator(this.text))
            .then((result) => {
              if (result === false) {
                this.loading = false;
                this.message = '';
              } else {
                this.addTag(this.text);
              }
            })
            .catch((e) => {
              this.loading = false;
              this.message = e?.message ?? '';
            });
        } else if (Array.isArray(this.validator)) {
          if (!new RegExp(this.validator[0]).test(this.text)) {
            this.loading = false;
            this.message = this.validator[1] || '校验不通过';
          } else {
            this.addTag(this.text);
          }
        } else {
          this.addTag(this.text);
        }
      },
      /* 移除tag */
      onClose(index) {
        if (this.beforeRemove && this.beforeRemove(index) === false) {
          return;
        }
        const data = this.data
          .slice(0, index)
          .concat(this.data.slice(index + 1, this.data.length));
        this.$emit('change', data);
      }
    }
  };
</script>

<style lang="scss">
  .ele-tags-input {
    margin-bottom: -10px;

    .el-tag {
      margin: 0 10px 10px 0;

      & + .el-tag {
        margin-left: 0;
      }
    }

    .el-button,
    .el-input {
      overflow: hidden;
      vertical-align: middle;
    }

    .el-button--mini {
      padding: 3px 5px;
    }

    .el-input--mini .el-input__inner {
      height: 20px;
      line-height: 1;
      padding: 0 5px;
    }

    .el-button--small {
      padding: 5px 8px;
    }

    .el-input--small .el-input__inner {
      height: 24px;
      line-height: 1;
      padding: 0 8px;
      font-size: 12px;
    }

    .el-button--medium {
      padding: 7px 10px;
      font-size: 12px;
    }

    .el-input--medium .el-input__inner {
      height: 28px;
      line-height: 1;
      padding: 0 10px;
      font-size: 12px;
    }

    .el-button--large {
      padding: 9px 10px;
      font-size: 12px;
    }

    .el-input--large .el-input__inner {
      height: 32px;
      line-height: 1;
      padding: 0 10px;
      font-size: 12px;
    }

    .el-input > .el-input__suffix > .el-input__suffix-inner {
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: center;

      & > .el-icon-loading {
        font-size: 12px;
        width: 12px;
        height: 12px;
        line-height: 12px;
        display: block;
      }
    }
  }
</style>
